import sys
import sqlite3
from datetime import datetime, timezone
from PyQt5.QtCore import Qt, pyqtSignal
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *

# 数据库日期时间适配器
def adapt_datetime(dt):
    return dt.isoformat()

def convert_datetime(text):
    return datetime.fromisoformat(text.decode())

sqlite3.register_adapter(datetime, adapt_datetime)
sqlite3.register_converter("datetime", convert_datetime)

class MemoryApp(QMainWindow):
    data_updated = pyqtSignal()

    def __init__(self):
        super().__init__()
        self.db = sqlite3.connect('cards.db', detect_types=sqlite3.PARSE_DECLTYPES)
        self.init_db()
        self.init_ui()
        self.load_cards()

    def init_db(self):
        c = self.db.cursor()
        c.execute('''CREATE TABLE IF NOT EXISTS cards
            (id INTEGER PRIMARY KEY,
             question TEXT,
             answer TEXT,
             proficiency INTEGER DEFAULT 0,
             modified DATETIME)''')
        c.execute('''CREATE TABLE IF NOT EXISTS tags
            (id INTEGER PRIMARY KEY, name TEXT UNIQUE)''')
        c.execute('''CREATE TABLE IF NOT EXISTS card_tags
            (card_id INTEGER, tag_id INTEGER,
             FOREIGN KEY(card_id) REFERENCES cards(id),
             FOREIGN KEY(tag_id) REFERENCES tags(id))''')
        self.db.commit()

    def init_ui(self):
        self.setWindowTitle('记忆训练系统')
        self.setGeometry(300, 300, 1000, 700)
        
        central = QWidget()
        self.setCentralWidget(central)
        layout = QHBoxLayout(central)
        
        # 左侧卡片列表
        self.card_list = QListWidget()
        self.card_list.itemDoubleClicked.connect(self.show_card_detail)
        self.card_list.setStyleSheet("""
            QListWidget {
                font-size: 14px;
                min-width: 300px;
                border-right: 1px solid #ddd;
            }
            QListWidget::item {
                padding: 12px;
                border-bottom: 1px solid #eee;
            }
        """)
        layout.addWidget(self.card_list)
        
        # 右侧详情面板
        right_panel = QVBoxLayout()
        
        # 卡片信息显示
        self.info_label = QLabel()
        self.info_label.setStyleSheet("color: #666; padding: 8px;")
        right_panel.addWidget(self.info_label)
        
        # 问题显示区域
        self.question_display = QTextEdit()
        self.question_display.setReadOnly(True)
        self.question_display.setStyleSheet("""
            font-size: 18px;
            padding: 20px;
            background: #f8f8f8;
            border-radius: 8px;
        """)
        right_panel.addWidget(self.question_display)
        
        # 操作按钮
        btn_layout = QHBoxLayout()
        self.add_btn = self.create_button("新建卡片", self.add_card, "#4CAF50")
        self.edit_btn = self.create_button("编辑卡片", self.edit_card, "#2196F3")
        self.study_btn = self.create_button("开始学习", self.start_study_session, "#FF9800")
        btn_layout.addWidget(self.add_btn)
        btn_layout.addWidget(self.edit_btn)
        btn_layout.addWidget(self.study_btn)
        right_panel.addLayout(btn_layout)
        
        layout.addLayout(right_panel)
        
        # 状态栏
        self.status = self.statusBar()
        self.update_status()
        
        # 快捷键设置
        QShortcut(Qt.Key_Delete, self).activated.connect(self.delete_card)
        QShortcut(Qt.Key_F5, self).activated.connect(self.load_cards)
        QShortcut(Qt.Key_E, self).activated.connect(self.edit_card)       # E键编辑
        QShortcut(Qt.Key_A, self).activated.connect(self.add_card)        # A键新建
        QShortcut(Qt.Key_S, self).activated.connect(self.start_study_session) # S键学习
        self.data_updated.connect(self.load_cards)

    def create_button(self, text, callback, color):
        btn = QPushButton(text)
        btn.setStyleSheet(f"""
            QPushButton {{
                background: {color};
                color: white;
                padding: 10px 20px;
                border-radius: 5px;
                margin: 5px;
            }}
            QPushButton:hover {{ background: {color}90; }}
        """)
        btn.clicked.connect(callback)
        return btn

    def load_cards(self):
        self.card_list.clear()
        c = self.db.cursor()
        c.execute("SELECT id, question, proficiency FROM cards ORDER BY modified DESC")
        for card in c.fetchall():
            item = QListWidgetItem()
            widget = QWidget()
            layout = QHBoxLayout(widget)
            
            # 进度条
            progress = QProgressBar()
            progress.setValue(card[2])
            progress.setTextVisible(False)
            progress.setStyleSheet("""
                QProgressBar {
                    height: 6px;
                    background: #eee;
                    border-radius: 3px;
                }
                QProgressBar::chunk {
                    background: #4CAF50;
                    border-radius: 3px;
                }
            """)
            
            # 问题摘要
            question_label = QLabel(card[1][:50] + "..." if len(card[1]) > 50 else card[1])
            question_label.setStyleSheet("font-size: 14px;")
            
            # 标签显示
            tags = self.get_card_tags(card[0])
            tag_label = QLabel(", ".join(t[1] for t in tags))
            tag_label.setStyleSheet("color: #888; font-size: 12px;")
            
            layout.addWidget(progress, 2)
            layout.addWidget(question_label, 5)
            layout.addWidget(tag_label, 3)
            item.setSizeHint(widget.sizeHint())
            item.setData(Qt.UserRole, card[0])
            self.card_list.addItem(item)
            self.card_list.setItemWidget(item, widget)

    def show_card_detail(self, item):
        card_id = item.data(Qt.UserRole)
        c = self.db.cursor()
        c.execute("SELECT * FROM cards WHERE id=?", (card_id,))
        card = c.fetchone()

        # 处理时间显示
        modified_time = card[4] if card[4] else datetime.now(timezone.utc)
        time_str = modified_time.strftime("%Y-%m-%d %H:%M") if isinstance(modified_time, datetime) else "未记录时间"

        self.question_display.setText(f"""
            <div style='font-size: 20px; margin-bottom: 15px;'>{card[1]}</div>
            <div style='color: #666; font-size: 16px;'>{card[2]}</div>
        """)

        tags = ", ".join(t[1] for t in self.get_card_tags(card_id))
        self.info_label.setText(f"""
            ID: {card_id} | 熟练度: {card[3]}% 
            | 最后修改: {time_str} 
            | 标签: {tags}
        """)

    def add_card(self):
        dialog = CardEditDialog("", "", [], self.get_all_tags(), self)
        if dialog.exec_() == QDialog.Accepted:
            question, answer, tags = dialog.get_data()
            self.save_card(None, question, answer, tags)
            self.data_updated.emit()

    def edit_card(self):
        if item := self.card_list.currentItem():
            card_id = item.data(Qt.UserRole)
            c = self.db.cursor()
            c.execute("SELECT * FROM cards WHERE id=?", (card_id,))
            card = c.fetchone()
            tags = self.get_card_tags(card_id)
            
            dialog = CardEditDialog(card[1], card[2], tags, self.get_all_tags(), self)
            if dialog.exec_() == QDialog.Accepted:
                question, answer, tags = dialog.get_data()
                self.save_card(card_id, question, answer, tags)
                self.data_updated.emit()

    def save_card(self, card_id, question, answer, tags):
        c = self.db.cursor()
        current_time = datetime.now(timezone.utc)  # 确保时间必有值

        try:
            if card_id:
                c.execute('''UPDATE cards SET 
                          question=?, answer=?, modified=?
                          WHERE id=?''', 
                         (question, answer, current_time, card_id))
            else:
                c.execute('''INSERT INTO cards 
                          (question, answer, modified)
                          VALUES (?, ?, ?)''', 
                         (question, answer, current_time))
                card_id = c.lastrowid
        
                # 更新标签关联
                c.execute("DELETE FROM card_tags WHERE card_id=?", (card_id,))
                for tag_id in tags:
                    c.execute("INSERT INTO card_tags VALUES (?, ?)", (card_id, tag_id))
                self.db.commit()
        except Exception as e:
            self.db.rollback()
            QMessageBox.critical(self, "错误", f"保存失败: {str(e)}")
        finally:
            self.db.commit()
    
    
    def delete_card(self):
        if item := self.card_list.currentItem():
            card_id = item.data(Qt.UserRole)
            reply = QMessageBox.question(
                self, "确认删除", 
                "确定要永久删除这个卡片吗？",
                QMessageBox.Yes | QMessageBox.No
            )
            if reply == QMessageBox.Yes:
                c = self.db.cursor()
                c.execute("DELETE FROM cards WHERE id=?", (card_id,))
                c.execute("DELETE FROM card_tags WHERE card_id=?", (card_id,))
                self.db.commit()
                self.load_cards()

    def start_study_session(self):
        tags = self.get_all_tags()
        if not tags:
            QMessageBox.information(self, "提示", "请先创建标签")
            return

        tag_names = [t[1] for t in tags]
        selected_tag, ok = QInputDialog.getItem(
            self, "选择学习标签", "请选择要学习的知识分类:", tag_names, editable=False
        )
        if ok and selected_tag:
            dialog = StudyDialog(selected_tag, self.db, self)
            dialog.exec_()
            self.load_cards()

    def get_all_tags(self):
        c = self.db.cursor()
        c.execute("SELECT id, name FROM tags ORDER BY name")
        return c.fetchall()

    def get_card_tags(self, card_id):
        c = self.db.cursor()
        c.execute('''SELECT t.id, t.name FROM tags t
                   JOIN card_tags ct ON t.id = ct.tag_id
                   WHERE ct.card_id = ?''', (card_id,))
        return c.fetchall()

    def update_status(self):
        c = self.db.cursor()
        c.execute("SELECT COUNT(*) FROM cards")
        total = c.fetchone()[0]
        self.status.showMessage(f"总卡片数: {total} | 双击查看详情 | Del删除卡片 | F5刷新列表")

class StudyDialog(QDialog):
    def __init__(self, tag_name, db_connection, parent=None):
        super().__init__(parent)
        self.db = db_connection
        self.tag_name = tag_name
        self.setWindowTitle(f"学习模式 - {tag_name}")
        self.setWindowModality(Qt.ApplicationModal)
        self.setMinimumSize(680, 500)
        
        self.cards = self.load_cards()
        self.current_index = 0
        self.init_ui()
        self.show_card()

    def next_card(self):
        if self.current_index < len(self.cards) - 1:
            self.current_index += 1
            self.answer_label.hide()
            self.show_card()
        else:
            self.close()  # 直接关闭不再提示

    def load_cards(self):
        c = self.db.cursor()
        query = '''SELECT c.* FROM cards c
                JOIN card_tags ct ON c.id = ct.card_id
                JOIN tags t ON ct.tag_id = t.id
                WHERE t.name = ?
                ORDER BY 
                    CASE 
                        WHEN proficiency < 30 THEN 0
                        WHEN proficiency < 70 THEN 1
                        ELSE 2
                    END,
                    RANDOM()'''
        c.execute(query, (self.tag_name,))
        return c.fetchall()

    def init_ui(self):
        layout = QVBoxLayout()
        
        # 进度显示
        self.progress_label = QLabel()
        self.progress_label.setAlignment(Qt.AlignCenter)
        self.progress_label.setStyleSheet("color: #666; font-size: 14px;")
        layout.addWidget(self.progress_label)
        
        # 卡片内容区域
        card_frame = QFrame()
        card_frame.setStyleSheet("""
            QFrame {
                background: white;
                border-radius: 10px;
                padding: 30px;
            }
        """)
        card_layout = QVBoxLayout(card_frame)
        
        self.question_label = QLabel()
        self.question_label.setWordWrap(True)
        self.question_label.setStyleSheet("font-size: 24px; color: #333;")
        self.question_label.setAlignment(Qt.AlignCenter)
        
        self.answer_label = QLabel()
        self.answer_label.setWordWrap(True)
        self.answer_label.setStyleSheet("""
            font-size: 20px; 
            color: #666;
            margin-top: 30px;
            padding: 20px;
            background: #f8f8f8;
            border-radius: 8px;
        """)
        self.answer_label.hide()
        
        card_layout.addWidget(self.question_label)
        card_layout.addWidget(self.answer_label)
        layout.addWidget(card_frame)
        
        # 操作按钮
        control_layout = QHBoxLayout()
        self.prev_btn = self.create_control_button("← 上一个", self.prev_card)
        self.show_btn = self.create_control_button("显示答案", self.toggle_answer)
        self.next_btn = self.create_control_button("下一个 →", self.next_card)
        control_layout.addWidget(self.prev_btn)
        control_layout.addWidget(self.show_btn)
        control_layout.addWidget(self.next_btn)
        layout.addLayout(control_layout)
        
        # 评分按钮
        rating_layout = QHBoxLayout()
        self.rate1_btn = self.create_rating_button("仍需复习", 1, "#ff6666")
        self.rate2_btn = self.create_rating_button("基本掌握", 2, "#66bb6a")
        self.rate3_btn = self.create_rating_button("完全掌握", 3, "#42a5f5")
        rating_layout.addWidget(self.rate1_btn)
        rating_layout.addWidget(self.rate2_btn)
        rating_layout.addWidget(self.rate3_btn)
        layout.addLayout(rating_layout)
        
        self.setLayout(layout)
        
        # 快捷键
        QShortcut(Qt.Key_Space, self).activated.connect(self.toggle_answer)
        QShortcut(Qt.Key_Q, self).activated.connect(self.prev_card)
        QShortcut(Qt.Key_E, self).activated.connect(self.next_card)
        QShortcut(Qt.Key_1, self).activated.connect(lambda: self.rate_card(1))
        QShortcut(Qt.Key_2, self).activated.connect(lambda: self.rate_card(2))
        QShortcut(Qt.Key_3, self).activated.connect(lambda: self.rate_card(3))

    def create_control_button(self, text, callback):
        btn = QPushButton(text)
        btn.setStyleSheet("""
            QPushButton {
                padding: 10px 20px;
                background: #f0f0f0;
                color: #666;
                border-radius: 5px;
            }
            QPushButton:hover {
                background: #e0e0e0;
            }
        """)
        btn.clicked.connect(callback)
        return btn

    def create_rating_button(self, text, rating, color):
        btn = QPushButton(text)
        btn.setStyleSheet(f"""
            QPushButton {{
                padding: 15px 25px;
                background: {color}20;
                color: {color};
                border: 2px solid {color};
                border-radius: 8px;
                font-weight: bold;
            }}
            QPushButton:hover {{
                background: {color}30;
            }}
        """)
        btn.clicked.connect(lambda: self.rate_card(rating))
        return btn

    def show_card(self):
        if not self.cards:
            self.close()
            return
            
        card = self.cards[self.current_index]
        self.question_label.setText(card[1])
        self.answer_label.setText(card[2])
        self.update_progress()

    def update_progress(self):
        text = f"当前进度：{self.current_index+1}/{len(self.cards)}"
        text += f"    |    当前熟练度：{self.cards[self.current_index][3]}%"
        self.progress_label.setText(text)

    def toggle_answer(self):
        self.answer_label.setVisible(not self.answer_label.isVisible())

    def prev_card(self):
        if self.current_index > 0:
            self.current_index -= 1
            self.answer_label.hide()
            self.show_card()
    
    def show_completion_dialog(self):
        dialog = QMessageBox(self)
        dialog.setWindowTitle("训练完成")
        dialog.setText("所有训练已完成，是否再次训练？")
        dialog.setIcon(QMessageBox.Question)
        
        restart_btn = dialog.addButton("&1 重新开始", QMessageBox.YesRole)
        close_btn = dialog.addButton("&2 返回主界面", QMessageBox.NoRole)
        
        restart_btn.setShortcut(QKeySequence("1"))
        close_btn.setShortcut(QKeySequence("2"))
        
        dialog.setStyleSheet("""
            QMessageBox {
                font-size: 14px;
            }
            QPushButton {
                min-width: 100px;
                padding: 8px;
            }
        """)
        
        dialog.exec_()
        return dialog.clickedButton() == restart_btn

    def restart_session(self):
        self.current_index = 0
        self.cards = self.load_cards()
        if self.cards:
            self.answer_label.hide()
            self.show_card()
        else:
            self.close()

    def rate_card(self, rating):
        card = self.cards[self.current_index]
        new_proficiency = card[3]
        
        if rating == 1:
            new_proficiency = max(0, new_proficiency - 20)
        elif rating == 2:
            new_proficiency = min(100, new_proficiency + 5)
        elif rating == 3:
            new_proficiency = min(100, new_proficiency + 20)
        
        c = self.db.cursor()
        c.execute('''UPDATE cards SET proficiency=?, modified=?
                  WHERE id=?''',
                 (new_proficiency, datetime.now(timezone.utc), card[0]))
        self.db.commit()
        
        self.next_card()
        self.cards = self.load_cards()

class CardEditDialog(QDialog):
    def __init__(self, question, answer, current_tags, all_tags, parent=None):
        super().__init__(parent)
        self.setWindowTitle("编辑卡片内容")
        self.setFixedSize(600, 500)
        
        layout = QVBoxLayout()
        
        # 问题输入
        self.question_edit = QTextEdit()
        self.question_edit.setPlainText(question)
        self.question_edit.setPlaceholderText("输入问题...")
        layout.addWidget(QLabel("问题:"))
        layout.addWidget(self.question_edit)
        
        # 答案输入
        self.answer_edit = QTextEdit()
        self.answer_edit.setPlainText(answer)
        self.answer_edit.setPlaceholderText("输入答案...")
        layout.addWidget(QLabel("答案:"))
        layout.addWidget(self.answer_edit)
        
        # 标签选择器
        self.tag_selector = TagSelector(current_tags, all_tags, self)
        layout.addWidget(QLabel("关联标签:"))
        layout.addWidget(self.tag_selector)
        
        # 操作按钮
        btn_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        btn_box.accepted.connect(self.accept)
        btn_box.rejected.connect(self.reject)
        layout.addWidget(btn_box)
        
        self.setLayout(layout)

    def get_data(self):
        return (
            self.question_edit.toPlainText().strip(),
            self.answer_edit.toPlainText().strip(),
            self.tag_selector.selected_tags()
        )

class TagSelector(QWidget):
    def __init__(self, current_tags, all_tags, parent):
        super().__init__(parent)
        self.db = parent.db if hasattr(parent, 'db') else None
        self.all_tags = {t[1]: t[0] for t in all_tags}
        self.current_tag_ids = {t[0] for t in current_tags}
        
        layout = QHBoxLayout()
        
        # 标签列表
        self.tag_list = QListWidget()
        self.tag_list.setSelectionMode(QListWidget.MultiSelection)
        self.load_tags(all_tags)
        layout.addWidget(self.tag_list)
        
        # 新建标签
        new_tag_layout = QVBoxLayout()
        self.new_tag_edit = QLineEdit()
        self.new_tag_edit.setPlaceholderText("输入新标签名称...")
        self.new_tag_btn = QPushButton("添加标签")
        self.new_tag_btn.clicked.connect(self.create_tag)
        new_tag_layout.addWidget(self.new_tag_edit)
        new_tag_layout.addWidget(self.new_tag_btn)
        layout.addLayout(new_tag_layout)
        
        self.setLayout(layout)

    def load_tags(self, tags):
        self.tag_list.clear()
        for tag_id, name in tags:
            item = QListWidgetItem(name)
            item.setData(Qt.UserRole, tag_id)
            item.setSelected(tag_id in self.current_tag_ids)
            self.tag_list.addItem(item)

    # def create_tag(self):
    #     name = self.new_tag_edit.text().strip()
    #     if name and name not in self.all_tags and self.db:
    #     # if name and name not in self.all_tags:
    #         c = self.db.cursor()
    #         c.execute("INSERT INTO tags (name) VALUES (?)", (name,))
    #         self.db.commit()
    #         self.all_tags[name] = c.lastrowid
    #         self.load_tags([(self.all_tags[name], name)])
    #         self.new_tag_edit.clear()
    def create_tag(self):
        name = self.new_tag_edit.text().strip()
        if name and name not in self.all_tags:
            c = self.parent().parent().db.cursor()
            c.execute("INSERT INTO tags (name) VALUES (?)", (name,))
            c.connection.commit()
            self.all_tags[name] = c.lastrowid
            self.load_tags([(self.all_tags[name], name)])

    def selected_tags(self):
        return [item.data(Qt.UserRole) for item in self.tag_list.selectedItems()]

if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.setStyle('Fusion')
    
    font = QFont()
    font.setFamily("微软雅黑")
    font.setPointSize(10)
    app.setFont(font)
    
    window = MemoryApp()
    window.show()
    sys.exit(app.exec_())